package com.shijie.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import com.shijie.constant.OtherExConstant;
import com.shijie.constant.IdKeyPrefix;
import com.shijie.dto.LoginDTO;
import com.shijie.dto.RegisterDTO;
import com.shijie.dto.UserUpdateDTO;
import com.shijie.entity.User;
import com.shijie.exception.AccountException;
import com.shijie.constant.AccountExConstant;
import com.shijie.mapper.AccountMapper;
import com.shijie.service.AccountService;
import com.shijie.utlis.RedisIdWorker;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
@RequiredArgsConstructor
public class AccountServiceImpl implements AccountService {

    private final AccountMapper accountMapper;

    private final RedisIdWorker redisIdWorker;

    private final StringRedisTemplate stringRedisTemplate;

    @Override
    public User register(RegisterDTO registerDTO) {
        if (registerDTO.getCheckCode() == null)
            throw new AccountException(OtherExConstant.CHECK_CODE_ERROR);

        User hasUser = accountMapper.getByUsername(registerDTO.getUsername());
        if (hasUser != null) {
            throw new AccountException(AccountExConstant.ACCOUNT_HAS_EXIST);
        }
        if (!registerDTO.getPassword().equals(registerDTO.getSurePassword())) {
            log.warn("注册密码错误");
            throw new AccountException(AccountExConstant.PASSWORD_ERROR);
        }

        long userId = redisIdWorker.nextId(IdKeyPrefix.USER_KEY);
        User user = User.builder()
                .userId(userId)
                .username(registerDTO.getUsername())
                .password(SaSecureUtil.md5(registerDTO.getPassword()))
                .role(User.Role.User)
                .build();

        if (!accountMapper.register(user))
            throw new AccountException(OtherExConstant.UNKNOWN_ERROR);

        return user;
    }

    @Override
    public User login(LoginDTO loginDTO) {
        if (loginDTO.getCheckCode() == null)
            throw new AccountException(OtherExConstant.CHECK_CODE_ERROR);

        User user = accountMapper.getByUsername(loginDTO.getUsername());
        if (user == null) {
            log.warn("登录账号不存在");
            throw new AccountException(AccountExConstant.ACCOUNT_NO_EXISTS);
        }
        if (!user.getPassword().equals(SaSecureUtil.md5(loginDTO.getPassword()))) {
            log.error("登录密码错误");
            throw new AccountException(AccountExConstant.PASSWORD_ERROR);
        }

        return user;
    }

    @Override
    public boolean updateInfo(UserUpdateDTO userUpdateDTO) {
        if (userUpdateDTO == null || userUpdateDTO.getUserId() == null) return false;
        User user = User.builder().userId(userUpdateDTO.getUserId()).build();
        String username = userUpdateDTO.getUsername();
        String oldPassword = userUpdateDTO.getOldPassword();
        String newPassword = userUpdateDTO.getNewPassword();

        // 规定用户名和密码不得同时更新
        if (StringUtils.hasText(username)) {
            user.setUsername(username);
        } else if (StringUtils.hasText(oldPassword) && StringUtils.hasText(newPassword)) {
            String password = accountMapper.getByUseId(userUpdateDTO.getUserId()).getPassword();
            if (!oldPassword.equals(password)) {
                throw new AccountException(AccountExConstant.PASSWORD_ERROR);
            }
            user.setPassword(password);
        }

        return accountMapper.updateInfo(user);
    }

    @Override
    public Integer checkCode(String username) {
        String codeStr = stringRedisTemplate.opsForValue().get("ch-code:" + username);
        if (StringUtils.hasText(codeStr))
            return Integer.valueOf(codeStr);

        Integer code = new Random().nextInt(100000, 1000000);
        stringRedisTemplate.opsForValue().set("ch-code:" + username, code.toString(),
                60L, TimeUnit.SECONDS);

        return code;
    }

    @Override
    public String resetPassword(String username) {
        User user = accountMapper.getByUsername(username);
        if (user == null)
            throw new AccountException(AccountExConstant.ACCOUNT_NO_EXISTS);

        String password = String.valueOf(new Random().nextInt(100000, 1000000));
        boolean ok = accountMapper.updateInfo(User.builder().userId(user.getUserId()).password(password).build());
        if (!ok)
            throw new AccountException(OtherExConstant.SYSTEM_FIXING);

        return password;
    }
}
